package com.web3.management.controller;

import com.web3.management.dto.ApiResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.web3.management.dto.request.CommandAckRequest;
import com.web3.management.dto.request.ManualUploadRequest;
import com.web3.management.dto.response.CommandDispatchResponse;
import com.web3.management.dto.tm.QrCapture;
import com.web3.management.dto.tm.SessionCapture;
import com.web3.management.entity.TmClient;
import com.web3.management.exception.BusinessException;
import com.web3.management.service.AccountCredentialService;
import com.web3.management.service.TmClientService;
import com.web3.management.service.TmCommandService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.util.List;

/**
 * Tampermonkey 客户端指令接口
 */
@Slf4j
@RestController
@RequestMapping("/tm")
@RequiredArgsConstructor
@Validated
public class TmCommandController {

    private final TmCommandService tmCommandService;
    private final TmClientService tmClientService;
    private final AccountCredentialService accountCredentialService;
    private final ObjectMapper objectMapper;

    @Value("${app.tm.auth-token:}")
    private String authToken;

    @GetMapping("/commands")
    public ApiResponse<List<CommandDispatchResponse>> pollCommands(@RequestParam @NotBlank String clientId,
                                                                   HttpServletRequest request) {
        verifyAuth(request);
        List<CommandDispatchResponse> commands = tmCommandService.pollCommands(clientId.trim());
        return ApiResponse.success(commands);
    }

    @PostMapping("/commands/{id}/ack")
    public ApiResponse<Void> acknowledge(@PathVariable Integer id,
                                          @RequestParam @NotBlank String clientId,
                                          @Valid @RequestBody CommandAckRequest requestBody,
                                          HttpServletRequest request) {
        verifyAuth(request);
        tmCommandService.handleAck(id, clientId.trim(), requestBody);
        return ApiResponse.success("指令处理成功", null);
    }

    @PostMapping("/manual/qr")
    public ApiResponse<Void> manualQr(@Valid @RequestBody ManualUploadRequest requestBody,
                                      HttpServletRequest request) {
        verifyAuth(request);
        TmClient client = tmClientService.findByClientId(requestBody.getClientId().trim())
                .orElseThrow(() -> new BusinessException("客户端不存在"));
        if (client.getAccountId() == null) {
            throw new BusinessException("客户端未绑定账号");
        }
        String payloadRaw;
        try {
            payloadRaw = objectMapper.writeValueAsString(requestBody.getPayload());
        } catch (Exception e) {
            throw new BusinessException("payload 格式错误");
        }
        QrCapture capture = null;
        try {
            capture = objectMapper.treeToValue(requestBody.getPayload(), QrCapture.class);
        } catch (Exception e) {
            throw new BusinessException("二维码 payload 解析失败");
        }
        String status = requestBody.getStatus() != null ? requestBody.getStatus() : "SUCCESS";
        accountCredentialService.handleQrCapture(client.getAccountId(), client.getClientId(), payloadRaw, capture,
                status, requestBody.getMessage());
        return ApiResponse.success("手动二维码上报成功", null);
    }

    @PostMapping("/manual/session")
    public ApiResponse<Void> manualSession(@Valid @RequestBody ManualUploadRequest requestBody,
                                           HttpServletRequest request) {
        verifyAuth(request);
        TmClient client = tmClientService.findByClientId(requestBody.getClientId().trim())
                .orElseThrow(() -> new BusinessException("客户端不存在"));
        if (client.getAccountId() == null) {
            throw new BusinessException("客户端未绑定账号");
        }
        String payloadRaw;
        try {
            payloadRaw = objectMapper.writeValueAsString(requestBody.getPayload());
        } catch (Exception e) {
            throw new BusinessException("payload 格式错误");
        }
        SessionCapture capture;
        try {
            capture = objectMapper.treeToValue(requestBody.getPayload(), SessionCapture.class);
        } catch (Exception e) {
            throw new BusinessException("登录信息 payload 解析失败");
        }
        String status = requestBody.getStatus() != null ? requestBody.getStatus() : "SUCCESS";
        accountCredentialService.handleSessionCapture(client.getAccountId(), client.getClientId(), payloadRaw, capture,
                status, requestBody.getMessage());
        return ApiResponse.success("手动登录信息上报成功", null);
    }

    private void verifyAuth(HttpServletRequest request) {
        if (!StringUtils.hasText(authToken)) {
            return;
        }
        String token = resolveToken(request);
        if (!authToken.equals(token)) {
            log.warn("Tampermonkey 接口未通过鉴权: token={}", token);
            throw new BusinessException("未授权的客户端请求");
        }
    }

    private String resolveToken(HttpServletRequest request) {
        String header = request.getHeader("Authorization");
        if (StringUtils.hasText(header) && header.startsWith("Bearer ")) {
            return header.substring(7);
        }
        String custom = request.getHeader("X-Auth-Token");
        if (StringUtils.hasText(custom)) {
            return custom;
        }
        return request.getParameter("token");
    }
}
